home *** CD-ROM | disk | FTP | other *** search
/ CD Actual 3 / CD ACTUAL 3.iso / linux / sonido / aumix-0.000 / aumix-0 / aumix-0.2 / aumix.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-11-28  |  14.8 KB  |  487 lines

  1. /*
  2.  *  Linux Audio Mixer - with ncurses interface
  3.  *
  4.  *  AUTHOR: Savio Lam (lam836@cs.cuhk.hk)
  5.  *
  6.  *  HISTORY:
  7.  *
  8.  *  23/10/93 - Version 0.1 released.
  9.  *
  10.  *  27/10/93 - Doesn't assume existence of any device (volume, bass, etc).
  11.  *           - Some minor bug fixes.
  12.  *
  13.  *  30/10/93 - Some bug fixes to work correctly with SB Pro.
  14.  *           - Should now work correctly when multiple copies are run
  15.  *             simutaneously.
  16.  *
  17.  *  28/11/93 - Version 0.2 released.
  18.  */
  19.  
  20. /*   This program is free software; you can redistribute it and/or
  21.      modify it under the terms of the GNU General Public License
  22.      as published by the Free Software Foundation; either version 2
  23.      of the License, or (at your option) any later version.
  24.  
  25.      This program is distributed in the hope that it will be useful,
  26.      but WITHOUT ANY WARRANTY; without even the implied warranty of
  27.      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  28.      GNU General Public License for more details.
  29.  
  30.      You should have received a copy of the GNU General Public License
  31.      along with this program; if not, write to the Free Software
  32.      Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
  33.  
  34.  
  35. #include <stdio.h>
  36. #include <fcntl.h>
  37. #include <unistd.h>
  38. #include <sys/ioctl.h>
  39. #include <sys/soundcard.h>
  40. #include <ncurses.h>
  41.  
  42. #define BG_COLOR 1
  43. #define TITLE_COLOR 2
  44. #define BOTTOM_LINE_COLOR 3
  45. #define PANEL_COLOR 4
  46. #define BORDER_COLOR 5
  47. #define HANDLE_COLOR 6
  48. #define TRACK_COLOR 7
  49. #define MARKING1_COLOR 8
  50. #define MARKING2_COLOR 9
  51. #define MARKING3_COLOR 10
  52. #define MARKING4_COLOR 11
  53. #define MARKING5_COLOR 12
  54. #define MARKING6_COLOR 13
  55. #define REC_LED_COLOR 14
  56. #define PLAY_LED_COLOR 15
  57. #define ACTIVE_COLOR 16
  58. #define INACTIVE_COLOR 17
  59. #define CONTROL_SPACING 8
  60. #define INCREMENT 2
  61.  
  62.  
  63. void InitColors(void);
  64. void DrawHandles(int dev);
  65. void Adjust(void);
  66.  
  67.  
  68. /*
  69.  * Global variables
  70.  */
  71. WINDOW *w_panel;
  72. int devmask = 0, recmask = 0, recsrc = 0, stereodevs = 0, mixer_fd;
  73. char *devname[SOUND_MIXER_NRDEVICES] = SOUND_DEVICE_LABELS;
  74. int level[SOUND_MIXER_NRDEVICES];
  75.  
  76. int main()
  77. {
  78.   int i, j;
  79.  
  80.   if ((mixer_fd = open("/dev/mixer", O_RDWR)) < 0) {
  81.     fprintf(stderr, "Error opening /dev/mixer.");
  82.     exit(1);
  83.   }
  84.   if (ioctl(mixer_fd, SOUND_MIXER_READ_DEVMASK, &devmask) == -1) {
  85.     perror("SOUND_MIXER_READ_DEVMASK");
  86.     exit(-1);
  87.   }
  88.   if (ioctl(mixer_fd, SOUND_MIXER_READ_RECMASK, &recmask) == -1) {
  89.     perror("SOUND_MIXER_READ_RECMASK");
  90.     exit(-1);
  91.   }
  92.   if (ioctl(mixer_fd, SOUND_MIXER_READ_RECSRC, &recsrc) == -1) {
  93.     perror("SOUND_MIXER_READ_RECSRC");
  94.     exit(-1);
  95.   }
  96.   if (ioctl(mixer_fd, SOUND_MIXER_READ_STEREODEVS, &stereodevs) == -1) {
  97.     perror("SOUND_MIXER_READ_STEREODEVS");
  98.     exit(-1);
  99.   }
  100.  
  101.  
  102.   if (!devmask) {
  103.     fprintf(stderr, "No device found.");
  104.     exit(-1);
  105.   }
  106.  
  107.   initscr();
  108.   leaveok(stdscr, TRUE);
  109.   keypad(stdscr, TRUE);
  110.   cbreak();
  111.   noecho();
  112.  
  113. #ifdef COLOR_CHECK
  114.   if (!has_colors())
  115.     fprintf(stderr, "WARNING: no color capability detected.");
  116. #endif
  117.  
  118.   InitColors();
  119.   move(0, 0);
  120.   attrset(COLOR_PAIR(TITLE_COLOR) | A_BOLD | A_ALTCHARSET);
  121.   printw("%c%c%c Linux Audio Mixer version 0.2"
  122.          "                               by Savio Lam %c%c%c",
  123.          178, 177, 176, 176, 177, 178);
  124.   attrset(COLOR_PAIR(BOTTOM_LINE_COLOR) | A_BOLD | A_ALTCHARSET);
  125.   move(LINES-1, 0);
  126.   addstr("  PgUp/PgDn - Prev/Next  SPACE - Rec/Play  UP/DOWN - Higher/Lower"
  127.          "  ESC - Exit   ");
  128.   refresh();
  129.  
  130.   w_panel = newwin(LINES - 2, COLS, 1, 0);
  131.   wattrset(w_panel, COLOR_PAIR(PANEL_COLOR) | A_DIM | A_ALTCHARSET);
  132.   wclear(w_panel);
  133.   wattrset(w_panel, COLOR_PAIR(BORDER_COLOR) | A_BOLD | A_ALTCHARSET);
  134.   wborder(w_panel, 219, 219, 223, 220, 219, 219, 219, 219);
  135.  
  136. /* Draw vertical controls */
  137.   for (i = 0; i < SOUND_MIXER_NRDEVICES-3; i++) {
  138.     for (j = 3; j < 14; j++) {
  139.       if (j < 7)
  140.         wattrset(w_panel, COLOR_PAIR(MARKING1_COLOR) | A_BOLD | A_ALTCHARSET);
  141.       else
  142.         if (j < 11) 
  143.           wattrset(w_panel, COLOR_PAIR(MARKING2_COLOR) | A_DIM | A_ALTCHARSET);
  144.         else
  145.           wattrset(w_panel, COLOR_PAIR(MARKING3_COLOR) | A_DIM | A_ALTCHARSET);
  146.       wmove(w_panel, j, i*CONTROL_SPACING+6);
  147.       wprintw(w_panel, "%c %c", 249, 249);
  148.       wattrset(w_panel, COLOR_PAIR(TRACK_COLOR) | A_DIM | A_ALTCHARSET);
  149.       wmove(w_panel, j, i*CONTROL_SPACING+7);
  150.       waddch(w_panel, 179);
  151.     }
  152.     if ((1 << (i+3)) & devmask) {
  153.       DrawHandles(i+3);
  154.     /* Print Rec/Play LED indicators */
  155.       if ((1 << (i+3)) & recmask) {
  156.         wattrset(w_panel,
  157.           COLOR_PAIR(((1 << (i+3)) & recsrc ? REC_LED_COLOR : PLAY_LED_COLOR))
  158.           | A_BOLD | A_ALTCHARSET);
  159.         wmove(w_panel, 2, i*CONTROL_SPACING+7);
  160.         waddch(w_panel, 223);
  161.       }
  162.       wattrset(w_panel, COLOR_PAIR(INACTIVE_COLOR) | A_BOLD | A_ALTCHARSET);
  163.     }
  164.     else
  165.       wattrset(w_panel, COLOR_PAIR(INACTIVE_COLOR) | A_DIM | A_ALTCHARSET);
  166.   /* Draw vertical control labels */
  167.     wmove(w_panel, 15, i*CONTROL_SPACING+6);
  168.     waddstr(w_panel, devname[i+3]);
  169.   }
  170.  
  171. /* Draw horizontal controls */
  172.   for (i = 1; i < 12; i++) {
  173.     if (i < 5)
  174.       wattrset(w_panel, COLOR_PAIR(MARKING6_COLOR) | A_DIM | A_ALTCHARSET);
  175.     else
  176.       if (i < 9)
  177.         wattrset(w_panel, COLOR_PAIR(MARKING5_COLOR) | A_BOLD | A_ALTCHARSET);
  178.       else
  179.         wattrset(w_panel, COLOR_PAIR(MARKING4_COLOR) | A_BOLD | A_ALTCHARSET);
  180.     wmove(w_panel, 18, i*2+10);
  181.     waddch(w_panel, 254);
  182.     wmove(w_panel, 17, i*2+50);
  183.     waddch(w_panel, 254);
  184.   }
  185.   wattrset(w_panel, COLOR_PAIR(TRACK_COLOR) | A_DIM | A_ALTCHARSET);
  186.   for (i = 1; i < 24; i++) {
  187.     wmove(w_panel, 19, i+10);
  188.     waddch(w_panel, 196);
  189.     wmove(w_panel, 18, i+50);
  190.     waddch(w_panel, 196);
  191.     wmove(w_panel, 20, i+50);
  192.     waddch(w_panel, 196);
  193.   }
  194.  
  195.   if (devmask & SOUND_MASK_VOLUME) {
  196.     DrawHandles(SOUND_MIXER_VOLUME);
  197.     wattrset(w_panel, COLOR_PAIR(INACTIVE_COLOR) | A_BOLD | A_ALTCHARSET);
  198.   }
  199.   else
  200.     wattrset(w_panel, COLOR_PAIR(INACTIVE_COLOR) | A_DIM | A_ALTCHARSET);
  201.   wmove(w_panel, 19, 4);
  202.   waddstr(w_panel, "Volume");
  203.  
  204.   if (devmask & SOUND_MASK_BASS) {
  205.     DrawHandles(SOUND_MIXER_BASS);
  206.     wattrset(w_panel, COLOR_PAIR(INACTIVE_COLOR) | A_BOLD | A_ALTCHARSET);
  207.   }
  208.   else
  209.     wattrset(w_panel, COLOR_PAIR(INACTIVE_COLOR) | A_DIM | A_ALTCHARSET);
  210.   wmove(w_panel, 18, 44);
  211.   waddstr(w_panel, "Bass");
  212.  
  213.   if (devmask & SOUND_MASK_TREBLE) {
  214.     DrawHandles(SOUND_MIXER_TREBLE);
  215.     wattrset(w_panel, COLOR_PAIR(INACTIVE_COLOR) | A_BOLD | A_ALTCHARSET);
  216.   }
  217.   else
  218.     wattrset(w_panel, COLOR_PAIR(INACTIVE_COLOR) | A_DIM | A_ALTCHARSET);
  219.   wmove(w_panel, 20, 44);
  220.   waddstr(w_panel, "Treble");
  221.  
  222.   wrefresh(w_panel);
  223.   Adjust(); 
  224.  
  225.   close(mixer_fd);
  226.   clear();
  227.   refresh();
  228.   endwin();
  229.  
  230.   return 0;
  231. }
  232. /* End of main() */
  233.  
  234. void InitColors(void)
  235. {
  236.   start_color();
  237.   init_pair(BG_COLOR, COLOR_WHITE, COLOR_BLACK);
  238.   init_pair(TITLE_COLOR, COLOR_WHITE, COLOR_RED);
  239.   init_pair(BOTTOM_LINE_COLOR, COLOR_CYAN, COLOR_BLUE);
  240.   init_pair(PANEL_COLOR, COLOR_BLACK, COLOR_BLACK);
  241.   init_pair(BORDER_COLOR, COLOR_BLACK, COLOR_BLACK);
  242.   init_pair(HANDLE_COLOR, COLOR_RED, COLOR_BLACK);
  243.   init_pair(TRACK_COLOR, COLOR_WHITE, COLOR_BLACK);
  244.   init_pair(MARKING1_COLOR, COLOR_CYAN, COLOR_BLACK);
  245.   init_pair(MARKING2_COLOR, COLOR_CYAN, COLOR_BLACK);
  246.   init_pair(MARKING3_COLOR, COLOR_BLUE, COLOR_BLACK);
  247.   init_pair(MARKING4_COLOR, COLOR_YELLOW, COLOR_BLACK);
  248.   init_pair(MARKING5_COLOR, COLOR_RED, COLOR_BLACK);
  249.   init_pair(MARKING6_COLOR, COLOR_RED, COLOR_BLACK);
  250.   init_pair(REC_LED_COLOR, COLOR_RED, COLOR_BLACK);
  251.   init_pair(PLAY_LED_COLOR, COLOR_GREEN, COLOR_BLACK);
  252.   init_pair(ACTIVE_COLOR, COLOR_YELLOW, COLOR_WHITE);
  253.   init_pair(INACTIVE_COLOR, COLOR_WHITE, COLOR_BLACK);
  254. }
  255. /* End of InitColors() */
  256.  
  257.  
  258. void DrawHandles(int dev)
  259. {
  260.   int temp;
  261.  
  262.   if (ioctl(mixer_fd, MIXER_READ(dev), &temp) == -1) {
  263.     perror("MIXER_READ");
  264.     endwin();
  265.     exit(-1);
  266.   }
  267.   if ((1 << dev) & stereodevs) {
  268.     /* Take the average of left and right settings */
  269.     temp = ((temp & 0x7F) + ((temp >> 8) & 0x7F)) / 2;
  270.     temp |= (temp << 8);
  271.     /* Reset so that left and right settings are equal */
  272.     if (ioctl(mixer_fd, MIXER_WRITE(dev), &temp) == -1) {
  273.       perror("MIXER_WRITE");
  274.       endwin();
  275.       exit(-1);
  276.     }
  277.   }
  278.   level[dev] = temp;
  279.   wattrset(w_panel, COLOR_PAIR(HANDLE_COLOR) | A_BOLD | A_ALTCHARSET);
  280.   switch (dev) {
  281.     case SOUND_MIXER_VOLUME:
  282.       wmove(w_panel, 19, 12 + ((temp & 0x7F)+2) / 5);
  283.       waddch(w_panel, 221);
  284.       break;
  285.     case SOUND_MIXER_BASS:
  286.       wmove(w_panel, 18, 52 + ((temp & 0x7F)+2) / 5);
  287.       waddch(w_panel, 221);
  288.       break;
  289.     case SOUND_MIXER_TREBLE:
  290.       wmove(w_panel, 20, 52 + ((temp & 0x7F)+2) / 5);
  291.       waddch(w_panel, 221);
  292.       break;
  293.     default:
  294.       wmove(w_panel, 13 - (((temp & 0x7F)+5) / 10), (dev-3)*CONTROL_SPACING+7);
  295.       waddch(w_panel, 219);
  296.   }
  297. }
  298. /* End of DrawHandles() */
  299.  
  300.  
  301. void Adjust(void)
  302. {
  303.   int key, incr, dir, dev, temp, temp1;
  304.  
  305. /* Find first existing device */
  306.   for (dev = 0; !(devmask & (1 << dev)); dev++);
  307. /* Highlight device label */
  308.   wattrset(w_panel, COLOR_PAIR(ACTIVE_COLOR) | A_BOLD | A_ALTCHARSET);
  309.   switch (dev) {
  310.     case SOUND_MIXER_VOLUME:
  311.       wmove(w_panel, 19, 4);
  312.       waddstr(w_panel, "Volume");
  313.       break;
  314.     case SOUND_MIXER_BASS:
  315.       wmove(w_panel, 18, 44);
  316.       waddstr(w_panel, "Bass");
  317.       break;
  318.     case SOUND_MIXER_TREBLE:
  319.       wmove(w_panel, 20, 44);
  320.       waddstr(w_panel, "Treble");
  321.       break;
  322.     default:
  323.       wmove(w_panel, 15, (dev-3)*CONTROL_SPACING+6);
  324.       waddstr(w_panel, devname[dev]);
  325.   }
  326.  
  327.   while (1) {
  328.     wmove(w_panel, 2, 2);
  329.     wrefresh(w_panel);
  330.     key = getch();
  331.     incr = 0;
  332.     dir = 0;
  333.     switch (key) {
  334.       case 27:          /* Escape */
  335.         return;
  336.       case KEY_PPAGE:    /* Prev Page */
  337.         dir = -1;
  338.       case 9:            /* TAB */
  339.       case KEY_NPAGE:    /* Next Page */
  340.         if (!dir)    /* if not Prev Page pressed */
  341.           dir = 1; 
  342.       /* Un-highlight current device label */
  343.         wattrset(w_panel, COLOR_PAIR(INACTIVE_COLOR) | A_BOLD | A_ALTCHARSET);
  344.         switch (dev) {
  345.           case SOUND_MIXER_VOLUME:
  346.             wmove(w_panel, 19, 4);
  347.             waddstr(w_panel, "Volume");
  348.             break;
  349.           case SOUND_MIXER_BASS:
  350.             wmove(w_panel, 18, 44);
  351.             waddstr(w_panel, "Bass");
  352.             break;
  353.           case SOUND_MIXER_TREBLE:
  354.             wmove(w_panel, 20, 44);
  355.             waddstr(w_panel, "Treble");
  356.             break;
  357.           default:
  358.             wmove(w_panel, 15, (dev-3)*CONTROL_SPACING+6);
  359.             waddstr(w_panel, devname[dev]);
  360.         }
  361.  
  362.         do {    /* Switch to next existing device */
  363.           if (dir == 1) {
  364.             dev++;
  365.             if (dev > SOUND_MIXER_NRDEVICES-1)
  366.               dev = 0;
  367.           }
  368.           else {
  369.             dev--;
  370.             if (dev < 0)
  371.               dev = SOUND_MIXER_NRDEVICES-1;
  372.           }
  373.         } while (!((1 << dev) & devmask));
  374.  
  375.       /* Highlight new device label */
  376.         wattrset(w_panel, COLOR_PAIR(ACTIVE_COLOR) | A_BOLD | A_ALTCHARSET);
  377.         switch (dev) {
  378.           case SOUND_MIXER_VOLUME:
  379.             wmove(w_panel, 19, 4);
  380.             waddstr(w_panel, "Volume");
  381.             break;
  382.           case SOUND_MIXER_BASS:
  383.             wmove(w_panel, 18, 44);
  384.             waddstr(w_panel, "Bass");
  385.             break;
  386.           case SOUND_MIXER_TREBLE:
  387.             wmove(w_panel, 20, 44);
  388.             waddstr(w_panel, "Treble");
  389.             break;
  390.           default:
  391.             wmove(w_panel, 15, (dev-3)*CONTROL_SPACING+6);
  392.             waddstr(w_panel, devname[dev]);
  393.         }
  394.         break;
  395.       case ' ':    /* Space */
  396.       /* Print Rec/Play LED indicators */
  397.         if ((1 << dev) & recmask) {
  398.           if (recsrc & (1 << dev))
  399.             recsrc &= ~(1 << dev);    /* Turn off recording */
  400.           else
  401.             recsrc |= (1 << dev);     /* Trun on recording */
  402.           if (ioctl(mixer_fd, SOUND_MIXER_WRITE_RECSRC, &recsrc) == -1) {
  403.             perror("SOUND_MIXER_WRITE_RECSRC");
  404.             endwin();
  405.             exit(-1);
  406.           }
  407.           wattrset(w_panel, COLOR_PAIR(((1 << dev) & recsrc
  408.               ? REC_LED_COLOR : PLAY_LED_COLOR)) | A_BOLD | A_ALTCHARSET);
  409.           wmove(w_panel, 2, (dev-3)*CONTROL_SPACING+7);
  410.           waddch(w_panel, 223);
  411.         }
  412.         break;
  413.       case '+':         /* '+'/UP/RIGHT */
  414.       case KEY_UP:
  415.       case KEY_RIGHT:
  416.         incr = INCREMENT;
  417.       case '-':         /* '-'/DOWN/LEFT */
  418.       case KEY_DOWN:
  419.       case KEY_LEFT:
  420.         if (!incr)    /* if not '+'/UP/RIGHT pressed */
  421.           incr = -INCREMENT;
  422.         temp = level[dev] & 0x7F;
  423.         temp1 = temp;
  424.         temp += incr;
  425.         if (incr > 0) {      /* Increase */
  426.           if (temp > 100)
  427.             temp = 100;
  428.         }
  429.         else                 /* Decrease */
  430.           if (temp < 0)
  431.             temp = 0;
  432.         temp |= (temp << 8);
  433.         level[dev] = temp;
  434.         if (ioctl(mixer_fd, MIXER_WRITE(dev), &temp) == -1) {
  435.           perror("MIXER_WRITE");
  436.           endwin();
  437.           exit(-1);
  438.         }
  439.         switch (dev) {
  440.           case SOUND_MIXER_VOLUME:
  441.           /* Erase handle from old position */
  442.             wattrset(w_panel, COLOR_PAIR(TRACK_COLOR) | A_ALTCHARSET);
  443.             wmove(w_panel, 19, 12 + (temp1+2) / 5);
  444.             waddch(w_panel, 196);
  445.           /* Draw handle at new position */
  446.             wattrset(w_panel, COLOR_PAIR(HANDLE_COLOR) | A_BOLD | A_ALTCHARSET);
  447.             wmove(w_panel, 19, 12 + ((level[dev] & 0x7F)+2) / 5);
  448.             waddch(w_panel, 221);
  449.             break;
  450.           case SOUND_MIXER_BASS:
  451.           /* Erase handle from old position */
  452.             wattrset(w_panel, COLOR_PAIR(TRACK_COLOR) | A_ALTCHARSET);
  453.             wmove(w_panel, 18, 52 + (temp1+2) / 5);
  454.             waddch(w_panel, 196);
  455.           /* Draw handle at new position */
  456.             wattrset(w_panel, COLOR_PAIR(HANDLE_COLOR) | A_BOLD | A_ALTCHARSET);
  457.             wmove(w_panel, 18, 52 + ((level[dev] & 0x7F)+2) / 5);
  458.             waddch(w_panel, 221);
  459.             break;
  460.           case SOUND_MIXER_TREBLE:
  461.           /* Erase handle from old position */
  462.             wattrset(w_panel, COLOR_PAIR(TRACK_COLOR) | A_ALTCHARSET);
  463.             wmove(w_panel, 20, 52 + (temp1+2) / 5);
  464.             waddch(w_panel, 196);
  465.           /* Draw handle at new position */
  466.             wattrset(w_panel, COLOR_PAIR(HANDLE_COLOR) | A_BOLD | A_ALTCHARSET);
  467.             wmove(w_panel, 20, 52 + ((level[dev] & 0x7F)+2) / 5);
  468.             waddch(w_panel, 221);
  469.             break;
  470.           default:
  471.           /* Erase handle from old position */
  472.             wattrset(w_panel, COLOR_PAIR(TRACK_COLOR) | A_ALTCHARSET);
  473.             wmove(w_panel, 13 - ((temp1+5) / 10),
  474.               (dev-3)*CONTROL_SPACING+7);
  475.             waddch(w_panel, 179);
  476.           /* Draw handle at new position */
  477.             wattrset(w_panel, COLOR_PAIR(HANDLE_COLOR) | A_BOLD | A_ALTCHARSET);
  478.             wmove(w_panel, 13 - (((level[dev] & 0x7F)+5) / 10),
  479.               (dev-3)*CONTROL_SPACING+7);
  480.             waddch(w_panel, 219);
  481.         }
  482.         break;
  483.     }
  484.   }
  485. }
  486. /* End of Adjust() */
  487.